#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <stdlib.h>
#include <netdb.h>



#define	BUF_SIZE	1024
#define	MSG_STR	"Hello Server, I connecting..."

void print_usage(const char *program_name)
{

	printf("\n%s -- 1.0.0(2018.11.4)\n", program_name);
			                
	printf(" Usage:(1) %s -i <server_ip> -p <server_port>  [-h <server_use_help>]\n", program_name);
	printf("       (2) %s -n <server_hostname> -p <server_port>  [-h <server_use_help>]\n", program_name);
	
	printf("	-i --ip		the server ip_address you want to connect\n") ;
	printf("        -p --port       the server listen port you want to connect\n") ;	
	printf("        -n --hostname   the server hostname you want to connect\n") ;	
	printf("        -h --help       the client file how to use\n");
	printf("        Notice: If use hostname to connect Server ,Information get Segmentation fault, Please check out the hostname is ture you input!\n");	

	return ;
}



int main(int argc, char** argv)
{
	int	conn_fd ;	
	struct	sockaddr_in serv_addr ;
	char	buf[BUF_SIZE] ;	
	int	rv = -1 ;
	int	opt = -1 ;
	int	port = 0 ;
	char*	ip = NULL;
	char*	hostname = NULL;

	struct hostent *hostnp;

	
	const char *short_opts = "n:i:p:h";


	const struct option long_opts[] = 	{
							{"help", no_argument, NULL, 'h'},
							{"hostname", required_argument,NULL,'n'},
					       		{"port", required_argument, NULL, 'p'},
							{"ip", required_argument, NULL, 'i'},
	                                        	{0, 0, 0, 0},
						};


	while ((opt= getopt_long(argc, argv, short_opts, long_opts,NULL)) != -1)
	        {
	               switch (opt)
	                {
				case 'p':
					port = atoi(optarg);
		                        break ;
				case 'i':
					ip = optarg ;
					break ;

				case 'n':
					hostname = optarg ;
					break ;

				case 'h':
					print_usage(argv[0]) ;
					return 0;
														
			}

		 }

        if( ( ( !port) || (!hostname) ) && ( (!ip) || (!port) )  )
	{    
		print_usage(argv[0]);
		return 0;
        }

	memset(buf, 0, sizeof(buf)) ;

	if ( hostname )
	{
		hostnp = gethostbyname(hostname) ;
		printf("hostname %s\n", hostnp->h_name);
		
		snprintf(buf, sizeof(buf), "%s",inet_ntoa(*(struct in_addr *)hostnp->h_addr_list[0]));
		ip = buf ;
		printf("addr:%s\n",ip) ;
	}


	conn_fd = socket( AF_INET, SOCK_STREAM, 0 ) ;

	if(conn_fd < 0)
	{
		printf("creat socket failure : %s\n", strerror(errno)) ;
		return -1 ;
	}

	printf("socket suceeful,connect file descriptor[%d]\n" ,conn_fd) ;

	memset(&serv_addr, 0, sizeof(serv_addr)) ;
	serv_addr.sin_port = htons(port) ;
	serv_addr.sin_family = AF_INET ;
	inet_aton(ip, &serv_addr.sin_addr);

	if( connect(conn_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0 )
	{
		printf("connect failure[%s:%d] : %s\n",  inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port), strerror(errno)) ;
		goto cleanup ;
	}
	printf("connect server[%s:%d] succeful!\n",  inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port)) ;



	if(write(conn_fd, MSG_STR, strlen(MSG_STR)) < 0 )
	{
		printf("Write to server failed: %s\n", strerror(errno)) ;
		goto cleanup ;
	}

	sleep(1) ;
	
	memset(buf, 0, sizeof(buf)) ;
	rv = read(conn_fd, buf, sizeof(buf)) ;
	if(rv < 0)
	{
		printf("read from server failed: %s\n", strerror(errno)) ;
		goto cleanup ;

	}
	
	printf("Read %d byte from server:' %s'\n", rv, buf) ;

		
	

	


cleanup:
	close(conn_fd) ;


	return 0 ;
}
